package com.sixth.docker.service.impl;

import cn.hutool.core.date.DateTime;

import cn.hutool.core.date.DateUtil;
import com.alibaba.nacos.shaded.org.checkerframework.checker.units.qual.A;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.sixth.core.entity.Scheduling;
import com.sixth.core.entity.User;
import com.sixth.core.feign.UserFeign;
import com.sixth.core.vo.R;
import com.sixth.docker.mapper.SchedulingMapper;
import com.sixth.docker.service.SchedulingService;
import com.sixth.docker.vo.SchedulingDto;
import com.sixth.docker.vo.SchedulingVo;
import com.sixth.docker.vo.SchedulingVo1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: sixth-hospital-parent
 * @description:
 * @author: 赵庆龙
 * @create: 2024-08-16 09:26
 **/
@Service
public class SchedulingServiceImpl implements SchedulingService {
    @Autowired
    private SchedulingMapper schedulingMapper;
    @Autowired
    private UserFeign userFeign;
    @Autowired
    private StringRedisTemplate redisTemplate;

    // 查询全部排班信息，包括从Redis获取当前号码
    public R<List<Scheduling>> selectAll(Integer deptId, String schedulingType, String subsectionType, String schedulingDay) {
        Map<String, Object> params = new HashMap<>();
        params.put("deptId", deptId);
        params.put("schedulingType", schedulingType);
        params.put("subsectionType", subsectionType);
        params.put("schedulingDay", schedulingDay);

        List<Scheduling> schedulings = schedulingMapper.selectAll(params);
        schedulings.forEach(scheduling -> {
            String key = "current_number:" + scheduling.getDeptId();  // 使用部门 ID 作为 Redis key 的一部分
            String currentNumber = redisTemplate.opsForValue().get(key);
            scheduling.setCurrentNumber(currentNumber != null ? Integer.parseInt(currentNumber) : 0);
        });
        return R.ok(schedulings);
    }


    // 初始化Redis中的当前号码
    @PostConstruct
    public void initializeCurrentNumbers() {
        List<Scheduling> allSchedulings = schedulingMapper.selectAll(null);
        allSchedulings.forEach(scheduling -> {
            String key = "current_number:" + scheduling.getDeptId();
            if (redisTemplate.opsForValue().get(key) == null) {
                redisTemplate.opsForValue().set(key, "1");  // 设置初始值为0
            }
        });
    }

    // 更新号码数，例如在新挂号时调用
    public void incrementCurrentNumber(int deptId) {
        String key = "current_number:" + deptId;
        redisTemplate.opsForValue().increment(key);
    }

    public R<Object> insertOrUpdate(SchedulingVo1 schedulingVo1) {
        String createBy = schedulingVo1.getCreateBy();
        LocalDate beginDate = LocalDate.parse(schedulingVo1.getBeginDate());
        List<SchedulingVo1.SchedulingItem> dataItems = schedulingVo1.getData();

        for (SchedulingVo1.SchedulingItem item : dataItems) {
            Integer deptId = item.getDeptId();
            List<String> schedulingTypes = item.getSchedulingType();
            String subsectionType = item.getSubsectionType();
            Integer userId = item.getUserId();

            if (schedulingTypes == null || schedulingTypes.size() != 7) {
                return R.error("排班类型列表长度必须为7");
            }

            for (int i = 0; i < schedulingTypes.size(); i++) {
                LocalDate date = beginDate.plusDays(i);
                String type = schedulingTypes.get(i);

                // 构造查询条件
                QueryWrapper<Scheduling> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("dept_id", deptId)
                        .eq("scheduling_day", date.format(DateTimeFormatter.ISO_LOCAL_DATE))
                        .eq("user_id", userId)
                        .eq("subsection_type", subsectionType);

                if (type == null || type.trim().isEmpty()) {
                    // 如果类型为空，则删除记录，不包括 scheduling_type 条件
                    int deletedRows = schedulingMapper.delete(queryWrapper);
                    System.out.println("删除的记录数量: " + deletedRows);
                } else {
                    // 如果类型不为空，检查是否存在记录
                    queryWrapper.eq("scheduling_type", type);
                    Scheduling existingScheduling = schedulingMapper.selectOne(queryWrapper);
                    Scheduling scheduling = new Scheduling();
                    scheduling.setDeptId(deptId);
                    scheduling.setSchedulingDay(date.format(DateTimeFormatter.ISO_LOCAL_DATE));
                    scheduling.setSubsectionType(subsectionType);
                    scheduling.setUserId(userId);
                    scheduling.setSchedulingType(type);

                    try {
                        if (existingScheduling != null) {
                            // 更新现有记录
                            UpdateWrapper<Scheduling> updateWrapper = new UpdateWrapper<>();
                            updateWrapper.eq("dept_id", deptId)
                                    .eq("scheduling_day", date.format(DateTimeFormatter.ISO_LOCAL_DATE))
                                    .eq("user_id", userId)
                                    .eq("subsection_type", subsectionType)
                                    .eq("scheduling_type", type);
                            int updatedRows = schedulingMapper.update(scheduling, updateWrapper);
                            System.out.println("更新的记录数量: " + updatedRows);
                        } else {
                            // 插入新记录
                            scheduling.setCreateBy(createBy);
                            scheduling.setCreateTime(new Date());
                            int insertedRows = schedulingMapper.insert(scheduling);
                            System.out.println("插入的记录数量: " + insertedRows);
                        }
                        // 强制执行SQL
                        forceSqlExecution();
                    } catch (DataIntegrityViolationException e) {
                        return R.error("数据插入或更新失败: " + e.getMessage());
                    }
                }
            }
        }

        return R.ok();
    }

// 假设这是一个方法，用于确保SQL语句被执行
private void forceSqlExecution() {
    // 这里可以尝试关闭当前连接以强制执行SQL
    // 注意：实际应用中需要根据具体环境调整
    // 例如，如果是Spring框架，可以通过`EntityManager`来控制
    // 或者使用`Connection`对象来关闭连接
}

    public R<Map<String, Object>> selectScheduling(SchedulingVo schedulingVo) {
        //根据部门id以及员工id查询值班医生的信息。
        Map<String, Object> params = new HashMap<>();
        params.put("userId", schedulingVo.getUserId());
        params.put("deptId", schedulingVo.getDeptId());
        //远程调用其他微服务的接口
        R<List<User>> schedulingUser = userFeign.findSchedulingUser(params);
        List<User> users = schedulingUser.getData();

        return findResult(users, schedulingVo);
    }


    private R<Map<String, Object>> findResult(List<User> users, SchedulingVo schedulingVo) {
        //创建一个当前时间。
        Date date = new Date();
        if (schedulingVo.getQueryDate() != null) {
            //判断你传入是周一还是周日
            int i = DateUtil.dayOfWeek(DateUtil.parse(schedulingVo.getQueryDate(), "yyyy-MM-dd"));
            if (i == 1) {//表示周日
                date = DateUtil.offsetDay(DateUtil.parse(schedulingVo.getQueryDate(), "yyyy-MM-dd"), 1);
            } else {
                date = DateUtil.offsetDay(DateUtil.parse(schedulingVo.getQueryDate(), "yyyy-MM-dd"), -1);
            }
        }

        //计算给定日期的这周开始日期和结束日期
        DateTime beginDate = DateUtil.beginOfWeek(date);
        DateTime endDate = DateUtil.endOfWeek(date);

        schedulingVo.setBeginDate(DateUtil.format(beginDate, "yyyy-MM-dd"));
        schedulingVo.setEndDate(DateUtil.format(endDate, "yyyy-MM-dd"));

        //根据vo查询值班表.
        List<Scheduling> schedulings = selectSchedulingByParams(schedulingVo);
        //创建一个集合DTO对象
        List<SchedulingDto> schedulingDtos = new ArrayList<>();
        for (User user : users) {
            Long userId = user.getUserId();
            //表示上午值班
            SchedulingDto schedulingDto1 = new SchedulingDto(userId, user.getDeptId(), "1", initMap(beginDate));
            //表示下午值班
            SchedulingDto schedulingDto2 = new SchedulingDto(userId, user.getDeptId(), "2", initMap(beginDate));
            //表示晚上值班
            SchedulingDto schedulingDto3 = new SchedulingDto(userId, user.getDeptId(), "3", initMap(beginDate));

            for (Scheduling scheduling : schedulings) {
                //值班类型 门诊 急诊
                String schedulingType = scheduling.getSchedulingType();
                //值班时间段 上午 下午 晚上
                String subsectionType = scheduling.getSubsectionType();
                //值班日期
                String schedulingDay = scheduling.getSchedulingDay();
                //值班医生的id
                Integer userId1 = scheduling.getUserId();
                if ((userId + "").equals(userId1 + "")) {
                    switch (subsectionType) {
                        case "1":
                            schedulingDto1.getRecord().put(schedulingDay, schedulingType);
                            break;
                        case "2":
                            schedulingDto2.getRecord().put(schedulingDay, schedulingType);
                            break;
                        case "3":
                            schedulingDto3.getRecord().put(schedulingDay, schedulingType);
                            break;

                    }
                }
            }
            schedulingDto1.setSchedulingType(schedulingDto1.getRecord().values());
            schedulingDto2.setSchedulingType(schedulingDto2.getRecord().values());
            schedulingDto3.setSchedulingType(schedulingDto3.getRecord().values());
            schedulingDtos.add(schedulingDto1);
            schedulingDtos.add(schedulingDto2);
            schedulingDtos.add(schedulingDto3);

        }

        Map<String, Object> result = new HashMap<>();
        result.put("schedulingDtos", schedulingDtos);
        result.put("startTimeThisWeek", DateUtil.format(beginDate, "yyyy-MM-dd"));
        result.put("endTimeThisWeek", DateUtil.format(endDate, "yyyy-MM-dd"));
        result.put("labelNames", getLables(beginDate));
        return R.ok(result);
    }

    //得到日期表头
    private List<String> getLables(DateTime beginDate) {
        List<String> labelNames = new ArrayList<>();
        for (int i = 0; i < 7; i++) {
            DateTime dateTime = DateUtil.offsetDay(beginDate, i);
            String week = DateUtil.format(dateTime, "yyyy-MM-dd") + getWeek(i);
            labelNames.add(week);
        }
        return labelNames;
    }

    private String getWeek(int i) {
        String week = "";
        switch (i) {
            case 0:
                week = "(周一)";
                break;
            case 1:
                week = "(周二)";
                break;
            case 2:
                week = "(周三)";
                break;
            case 3:
                week = "(周四)";
                break;
            case 4:
                week = "(周五)";
                break;
            case 5:
                week = "(周六)";
                break;
            case 6:
                week = "(周日)";
                break;
        }
        return week;
    }

    //设置一周的上午 下午 晚上的默认值班
    private Map<String, String> initMap(DateTime beginDate) {
        Map<String, String> map = new LinkedHashMap<>(); //和你添加的顺序有关
        for (int i = 0; i < 7; i++) {
            DateTime dateTime = DateUtil.offsetDay(beginDate, i);
            map.put(DateUtil.format(dateTime, "yyyy-MM-dd"), "");
        }
        return map;
    }


    private List<Scheduling> selectSchedulingByParams(SchedulingVo schedulingVo) {
        System.out.println(schedulingVo);
        QueryWrapper<Scheduling> wrapper = new QueryWrapper<>();
        if (Objects.nonNull(schedulingVo.getUserId())) {
            wrapper.eq("user_id", schedulingVo.getUserId());
        }
        if (Objects.nonNull(schedulingVo.getDeptId())) {
            wrapper.eq("dept_id", schedulingVo.getDeptId());
        }
        if (Objects.nonNull(schedulingVo.getBeginDate())) {
            wrapper.between("scheduling_day", schedulingVo.getBeginDate(), schedulingVo.getEndDate());
        }
        return schedulingMapper.selectList(wrapper);
    }

}


